package com.beerandjesus.sportofkings.handicapper.dao;

import com.beerandjesus.sportofkings.handicapper.model.*;

import java.util.List;
import java.math.BigDecimal;

import org.hibernate.Query;
import org.hibernate.Criteria;
import org.apache.log4j.Logger;

/**
 * Date: Sep 8, 2012
 * Time: 5:03:25 PM
 */
public class JockeyHibernateDAO extends AbstractHibernateDAO implements JockeyDAO {

    private static final Logger LOG = Logger.getLogger(JockeyHibernateDAO.class);
    
    public void buildDatabase() throws DAOException {
        dropAndCreate(DROP_TABLE_STMT, CREATE_TABLE_STMT, LOG);
        dropAndCreate(DROP_TABLE + JOCKEY_RATING_THRESHOLD, CREATE_TABLE + JOCKEY_RATING_THRESHOLD + JOCKEY_RATING_THRESHOLD_DEF, LOG);
        dropAndCreate(DROP_TABLE + JOCKEY_PERFORMANCE, CREATE_TABLE + JOCKEY_PERFORMANCE + JOCKEY_PERFORMANCE_DEF, LOG);
        // Set up a default jockeyt rating threshold
        JockeyRatingThresholdImpl thresh = new JockeyRatingThresholdImpl();
        thresh.setActive(true);
        thresh.setLeading(new BigDecimal(.20, JOCKEY_STATS_MATH_CONTEXT));
        thresh.setExcellent(new BigDecimal(.16, JOCKEY_STATS_MATH_CONTEXT));
        thresh.setGood(new BigDecimal(.10, JOCKEY_STATS_MATH_CONTEXT));
        thresh.setName("Default");
        save(thresh);
    }

    public int getRowCount() throws DAOException {
        Query q = getSession().createQuery("select count(j) from JockeyRatingImpl j");
        Long count = (Long) q.uniqueResult();
        return (count == null ? 0 : count.intValue());
    }

    public int getJockeyPerformanceRowCount() throws DAOException {
        Query q = getSession().createQuery("select count(j) from JockeyPerformanceImpl j");
        Long count = (Long) q.uniqueResult();
        return (count == null ? 0 : count.intValue());
    }

    public JockeyRating getJockeyRatingByName(String name) throws DAOException {
        Query q = getSession().createQuery("from JockeyRatingImpl where name = :name");
        q.setString("name", name.toLowerCase());
        return (JockeyRating) q.uniqueResult();
    }

    public void save(JockeyRating rating) throws DAOException {
        JockeyRatingImpl r = new JockeyRatingImpl();
        r.setJockeyName(rating.getJockeyName().toLowerCase());
        r.setRating(rating.getRating());
        getSession().merge(r);
    }

    @SuppressWarnings("unchecked")
    public List<JockeyRating> getAllJockeyRatings() throws DAOException {
        Query q = getSession().createQuery("from JockeyRatingImpl");
        return q.list();
    }

    @SuppressWarnings("unchecked")
    public List<JockeyRatingThreshold> getAllJockeyRatingThresholds() throws DAOException {
        return getSession().createQuery("from JockeyRatingThresholdImpl").list();
    }

    public void save(JockeyRatingThreshold jrt) throws DAOException {
        getSession().merge(jrt);
        if (jrt.getActive()) {
            // Make sure all other rating thresholds are inactive
            Query q = getSession().createQuery("update JockeyRatingThresholdImpl set active = :active where name != :name");
            q.setBoolean("active", Boolean.FALSE);
            q.setString("name", jrt.getName());
            q.executeUpdate();
        }
    }

    @SuppressWarnings("unchecked")
    public JockeyRatingThreshold getJockeyRatingThresholdByName(String name) throws DAOException {
        if (name == null) {
            return null;
        }
        Query q = getSession().createQuery("from JockeyRatingThresholdImpl where name = :name");
        q.setString("name", name);
        return (JockeyRatingThreshold) q.uniqueResult();
    }

    public void delete(JockeyRatingThreshold thresh) throws DAOException {
        JockeyRatingThreshold byName = getJockeyRatingThresholdByName(thresh.getName());
        if (byName != null) {
            if (byName.getActive()) {
                throw new DAOException("Jockey rating threshold '" + thresh.getName() + "' is active -- cannot delete it");
            }
            getSession().delete(byName);
        }
    }

    public void save(JockeyPerformance perf) throws DAOException {
        JockeyPerformanceImpl p = new JockeyPerformanceImpl();
        p.setName(perf.getName().toLowerCase());
        p.setWinRatio(perf.getWinRatio());
        getSession().merge(p);
    }

    public JockeyPerformance getJockeyPerformanceByName(String name) throws DAOException {
        if (name == null || name.equals("")) {
            return null;
        }
        Query q = getSession().createQuery("from JockeyPerformanceImpl where name = :name");
        q.setString("name", name.toLowerCase());
        return (JockeyPerformance) q.uniqueResult();
    }

    public JockeyRatingThreshold getActiveJockeyRatingThreshold() {
        Query q = getSession().createQuery("from JockeyRatingThresholdImpl jp where active = :active");
        q.setBoolean("active", true);
        List list = q.list();
        if (list.size() == 0) {
            return null;
        }
        return (JockeyRatingThreshold) list.get(0);
    }

    @SuppressWarnings("unchecked")
    public List<JockeyPerformance> getAllJockeyPerformances() {
        Criteria c = getSession().createCriteria(JockeyPerformanceImpl.class);
        return c.list();
    }
}
